#pragma once
#ifndef READINBITSET_H_
#define READINBITSET_H_
#include "ReadsFileParser.h"
#include "ReadInBits.h"
#include "ColorSpaceRead.h"
#include "ShortReadUtil.h"
#include "MismatchScores.h"
#include "ReadsQualScores.h"
#include "Filename.h"
#include "stdafx.h"
#include <vector>
#include <iostream>
#include <string>
using namespace std;
// each time read in one million reads as buffering
const unsigned int BUFFERED_READS_SIZE = 1000000;
// const unsigned int BUFFERED_READS_SIZE = 1000;

class CReadInBitsSet
{
public:
    CReadInBitsSet(void);
    CReadInBitsSet(unsigned int Capacity, unsigned int uiReadLength, unsigned int allowedNumOfNinRead = 0);
    // Generate set given a file with reads and readLength (must be known in advance)
    CReadInBitsSet(const char* InputFile, const char* fileFormat, unsigned int uiReadLength\
                   , unsigned int allowedNumOfNinRead, unsigned int uiReadStartIndex);
    virtual ~CReadInBitsSet();
    void init(const char* InputFile, const char* fileFormat, unsigned int uiReadLength\
              , unsigned int allowedNumOfNinRead, unsigned int uiReadStartIndex);
    int clearReads(int capacity);
    inline void reserve(int capacity) {
        this->pReadsSet->reserve(capacity);
        this->pReadsID->reserve(capacity);
    }
    inline int capacity(void) {
        return(pReadsSet->capacity());
    }
    inline int size(void) {
        return(pReadsSet->size());
    }
    inline unsigned int getReadLength() {
        return(uiRead_Length);
    };
    inline bool isSOLiDReadFormat(void) {
        return(this->cFileType == 'Q' || this->cFileType == 'S');
    }
    inline bool bGetQScores(void) {
        return(this->cFileType == 'Q' || this->cFileType == 'q');
    }
    inline bool bStoreQS(void) {
        return(this->pQualScores != NULL);
    };
    inline const char* readSetName(void) {
        return(InputFile);
    };
    const char* get_Next_Read(void);
    void flushParser(void);
    bool handleBadRead(void);
    void removeExtraTags(void);
    void getQualityScoresFromQUAL(void);


    // get reads from the file and store (append) in a vector. Return how many reads are read-in.
    unsigned int openAFileReady2GetRead(const char* InputFile, const char* fileFormat, unsigned int uiReadStartIndex);
    unsigned int openAFileReady2GetReadQSinQUAL(const char* InputFile, unsigned int readQsLength);
    unsigned int get_next_capacity_reads(int capacity, char sep = ',');
    void ignoreQScores(void);

    void get_read_id(int no, char* readId);
    void save_next_read_id(const char* tagLine, char sep = ',');
    void save_next_read_id(char sep = ',');
    bool save_next_read(const char* readSeq, bool bSOLiDReadFormat);
    bool save_next_read(bool bSOLiDReadFormat, bool bGetQScores);
    bool save_next_colorStr_as_a_read(const char* readSeq);
    inline const char* getQScoresPtr(int readId);

    vector<CReadInBits>* pReadsSet;
    vector<CReadID>* pReadsID; // The vector keep tags of the reads
    bool bDiscardReadWithN;
    unsigned int allowedNumOfNinRead;
    unsigned int  uiRead_Length;
    unsigned int  uiNo_of_Reads;
    unsigned int  uiNo_of_Bad_Reads;
    //A char flag used to record the input file type, example F for fasta, S for .seq.txt, A for .realign
    char cFileType;
    char InputFile[FILENAME_MAX];
    // Keep the info of the quality score
    CReadsQualScores* pQualScores;
    // Keep the info of the best alignments score + # of best alignments
    CMismatchScores* pMismatchScores;
    void setBadReadOutputFile(FileOutputBuffer* pOut);
protected:
    CReadsFileParser parser;
private:
    void initialization(void);
};

inline const char* CReadInBitsSet::getQScoresPtr(int readId)
{
    if (this->pQualScores == NULL) {
        return(NULL);
    } else {
        return(this->pQualScores->qScores((unsigned int)readId));
    }
}

// This function prints out the reads that have mapping worse than the missMatchScoreT
int printMissReads(const char* outputfile, CReadInBitsSet& readSet, int missMatchScoreT);
#endif /* CREADSSET_H_ */


